<?php


/**
 * PDF Invoicing Solution for VirtueMart & Joomla!
 * 
 * @package   VM Invoice
 * @version   2.0.24
 * @author    ARTIO http://www.artio.net
 * @copyright Copyright (C) 2011 ARTIO s.r.o. 
 * @license   GNU/GPLv3 http://www.artio.net/license/gnu-general-public-license
 */

class TableVm2OrderItem extends JTable
{
    var $virtuemart_order_item_id = null;
    var $virtuemart_order_id = null;
    var $virtuemart_vendor_id = null;
    var $virtuemart_product_id = null;
    var $order_item_sku = null;
    var $order_item_name = null;
    var $product_quantity = null;
    var $product_item_price = null;
    var $product_tax = null;
    var $product_basePriceWithTax = null;
    var $product_final_price = null;
    var $product_subtotal_discount = null;
    var $product_subtotal_with_tax = null;
    var $order_item_currency = null;
    var $order_status = null;
    var $product_attribute = null;
    var $created_on = null;
    var $created_by = null;
    var $modified_on = null;
    var $modified_by = null;
    
    function __construct(&$db)
    {
        parent::__construct('#__virtuemart_order_items', 'virtuemart_order_item_id', $db);
    }

    function store(&$data)
    {
    	$rename = array(  //if we are using other "inner" name than db name
    		'virtuemart_order_item_id'=>'order_item_id',
    		'virtuemart_vendor_id'=>'vendor_id',
    		'virtuemart_product_id' => 'product_id', 
    		'product_subtotal_discount' => 'product_price_discount'
    	);
    	
        $now = gmdate('Y-m-d H:i:s');
        $currentUser = JFactory::getUser();
        
        $vars = get_object_vars($this);
        
        //order item status. DON't SAVE it here (only on initial??). Instead use VM function for update item status.
        //but only if not checked "update for all items" (?) not needed. if it is same status, vm should not not do anything.
        
        //SCENARIO: if adding or deleting product, bind order status and use own function to adjust stock
        //if not, DONT change status and adjust stock, instead save first and than call VM function to change status separately
        $newStatuses = array();
        $stored = array();
        
        foreach ($data['order_item_id'] as $i => $orderItemId) { //items to update/add
        	
            foreach ($vars as $param => $value)
                if ($param[0] != '_'){
                	$name = (isset($rename[$param]) ? $rename[$param] : $param);
                	if (isset($data[$name]))
                    	$this->$param = @reset(array_slice($data[$name], $i, 1));
             	}
             	
            $this->order_status = null; //NOT update status here. use always VM functions (to adjust stock)
            if (!$this->virtuemart_order_item_id)
                $this->order_status = 'N';	//if ADDING product, set as NEW.
            
            //if changed quantity, set status to "N" to neutralize stock, than (after save) set new status with new quantity. thats only way to use VM functions.
            if ($this->virtuemart_order_item_id){
            	$class  = get_class($this);
            	$oldTable = new $class($this->_db);
            	if (!($oldTable->load($this->virtuemart_order_item_id)))
            		JError::raiseWarning(0, 'Cannit load old row for ordered item '.$this->virtuemart_order_item_id.'. '.$oldTable->getError());
            	elseif ($oldTable->product_quantity!=$this->product_quantity) //changed quantity!
            		$this->changeItemStatus((int)$data['order_id'], $this->virtuemart_order_item_id, 'N'); //change status to "N" (reset stock) with old quantity
            	unset($oldTable);
            }
            
            $this->virtuemart_order_id = $data['order_id'];
	        $this->modified_on = $now;
	        $this->modified_by = $currentUser->id;
	        if (!$this->virtuemart_order_item_id){
	            $this->created_on = $now;
	            $this->created_by = $currentUser->id;
	        }
	        
	        //compute rest of prices (see recomputeOrder function comments to explain/guess of prices meanings)
	        $this->product_basePriceWithTax = $this->product_item_price + $this->product_tax;
	        $this->product_final_price = $this->product_basePriceWithTax - $this->product_subtotal_discount;
	        
	        //since VM 2.0.11, product_tax is stored per-item (in older versions it was for item*quantity)
			InvoiceHelper::importVMFile('version.php');
			$taxPerItem = class_exists('vmVersion') ? (version_compare(vmVersion::$RELEASE, '2.0.11') >= 0) : true; 
	        $this->product_tax = $taxPerItem ? $this->product_tax : ($this->product_tax*$this->product_quantity); //VM2 since version 2.0.11: tax is stored for 1 item
	        
	        $this->product_subtotal_discount = $this->product_subtotal_discount * $this->product_quantity;
	        $this->product_subtotal_with_tax = $this->product_basePriceWithTax * $this->product_quantity + $this->product_subtotal_discount;
	        
	        $this->order_item_currency = null;
	        if (!trim($this->product_attribute))
	        	$this->product_attribute = null;
	        	
        	//store item
        	parent::store();
        	
            $stored[] = $this->virtuemart_order_item_id;
            $newStatuses[$this->virtuemart_order_item_id] = !empty($data['order_status'][$i]) ? $data['order_status'][$i] : (!empty($data['status']) ? $data['status'] : 'P'); //status not selected: use order status, if not selected, use pending
        }
        
        //items to delete:

        //change item status to "Cancelled" (to adjust stock) and than delete products
        $this->_db->setQuery('SELECT virtuemart_product_id, virtuemart_order_item_id FROM `#__virtuemart_order_items` WHERE `virtuemart_order_id` = ' .(int) $data['order_id'] . ($stored ? ' AND `virtuemart_order_item_id` NOT IN (' . implode(',', $stored) . ')' : ''));
        if ($itemsDelete = $this->_db->loadObjectList())
        	foreach ($itemsDelete as $itemDelete)
        		$this->changeItemStatus((int)$data['order_id'], $itemDelete->virtuemart_order_item_id, 'X');
        		
        //delete items
        $this->_db->setQuery('DELETE FROM `#__virtuemart_order_items` WHERE `virtuemart_order_id` = ' . (int)$data['order_id'] . ($stored ? ' AND `virtuemart_order_item_id` NOT IN (' . implode(',', $stored) . ')' : ''));
        $this->_db->query();

        //now update order status for edited/added items
        $this->_db->setQuery('SELECT virtuemart_order_item_id FROM `#__virtuemart_order_items` WHERE `virtuemart_order_id` = ' . (int)$data['order_id']);
        
        foreach ($this->_db->loadResultArray() as $orderItemId)
        	if (isset($newStatuses[$orderItemId]))
        		$this->changeItemStatus((int)$data['order_id'], $orderItemId, $newStatuses[$orderItemId]);     

        return true;
    }
    
    /**
     * Use VM code for change item status. Or just update stock when quantity changes.
     */
    function changeItemStatus($orderId, $orderItemId, $newStatus)
    {
    	$formerView = JRequest::getVar('view');
		JRequest::setVar('view','orders'); //this is also for VM checkFilterDir function
							
    	InvoiceHelper::importVMFile('helpers/vmmodel.php');
    	InvoiceHelper::importVMFile('models/orders.php');
    	InvoiceHelper::importVMFile('tables/order_items.php');
    	InvoiceHelper::importVMFile('tables/orders.php');
    	$model = VmModel::getModel('orders');
    	
    	$input = array();
    	$input[$orderItemId] = array('order_status' => $newStatus);
    		
		foreach ($input as $key=>$value) {

			if (!isset($value['comments'])) $value['comments'] = '';

			$data = (object)$value;
			$data->virtuemart_order_id = $orderId;

			$model->updateSingleItem((int)$key, $data);
		}
		
		JRequest::setVar('view',$formerView);
    }
    
    
    /**
     * Only change status + adjust stock of ordered items
     * 
     * @param int $orderId
     * @param string $status
     */
    /*
    function changeItemsStatus($orderId,$status)
    {
    	$db = JFactory::getDBO();
    	$db->setQuery('SELECT virtuemart_order_item_id FROM #__virtuemart_order_items WHERE virtuemart_order_id='.(int)$orderId);
    	$itemIDs = $db->loadResultArray();
    	
    	foreach ($itemIDs as $itemID)
        	$this->updateVMStock(null, $status, null, $itemID); //update VM stock
    	
    	$db->setQuery('UPDATE #__virtuemart_order_items SET order_status = '.$db->Quote($status).' WHERE virtuemart_order_id='.(int)$orderId);
    	return $db->query();
    }
    */
    
    /**
     * Update VM product stock and sales. Needs to be called before ordered items DB change! (to get "old" status and number of current pieces from db)
     * 
     * @param int	 		new quantity. if null, its assumed it is same as old quantity
     * @param string/bool	new item status
     * @param int	 		product id
     * @param int/null 		current edited order_item id, null if new
     */
    /*
    function updateVMStock($newQuantity, $newStatus, $product_id, $order_item_id = null)
    {
    	//TODO: update VM stock ONLY when product is ADDED or DELETED, NOT 
    		        
    	//if it is "own product"
    	if (empty($product_id) && empty($order_item_id))
    		return true;
    	
    	//get number of currently ordered pieces (existing item)
    	if (!empty($order_item_id)){
    		$this->_db->setQuery('SELECT order_status,product_quantity, virtuemart_product_id FROM `#__virtuemart_order_items` WHERE `virtuemart_order_item_id` = '.(int)$order_item_id);
        	$oldItem = $this->_db->loadObject();
    	}
    	if (!empty($oldItem)){
    		$oldQuantity = $oldItem->product_quantity;
    		$oldStatus = $oldItem->order_status;
    		
    		if (is_null($newQuantity)) //new quantity not passsed, use old
    			$newQuantity = $oldQuantity;
    			
    		if (!$product_id) //product id nit passed use stored
    			$product_id = $oldItem->virtuemart_product_id;
    	}
    	else {  //new item
    		$oldQuantity = 0;
    		$oldStatus = false; 
    	}
    	
    	//if it is "own product"
    	if (empty($product_id))
    		return true;

    	//EXISTING ITEM. use VM function to update status + stock.
    	if ($newStatus!==false && $oldStatus!==false && $order_item_id)
    	{
    		$this->changeItemStatus($this->virtuemart_order_id, $order_item_id, $newStatus);
    	}
    	
        $stockOut = array('S'); //product is out of shop (from VM handleStockAfterStatusChangedPerProduct fnc)
        $reserved =  array('P','C'); //product is on shop, but reserved
        $change = array();
        
        //product_in_stock = is always same until is product S = shipped, than is substracted
        //product_ordered = number of NOT SHIPPED orders of that product
        //product_sales  = seems unused in VM2
        
    	if ($newStatus===false) //product is DELETED from order
    	{
    		//is was old status S
    		if (in_array($oldStatus,$stockOut)) //add back to stock
	    		$change[]=' product_in_stock = product_in_stock + '.(int)$oldQuantity;

    		//old status was resrrved, was only in ordered quantity
    		elseif (in_array($oldStatus,$reserved)) //substract from number of ordered products
    			$change[]=' product_ordered = product_ordered - '.(int)$oldQuantity; 		
    		//else no change
    	}
    	elseif ($oldStatus===false) //product is ADDED to order
    	{
    		if (in_array($newStatus,$stockOut)) //is directly shipped, substract straight from stock
    			$change[]=' product_in_stock = product_in_stock - '.(int)$newQuantity;
    		
    		elseif (in_array($newStatus,$reserved)) //added as reserved
    			$change[]=' product_ordered = product_ordered + '.(int)$newQuantity;
    	}
    	else { //ordered item is CHANGED at order

    		$inStock = 0;
    		$ordered = 0; //initial SQL values
    		
    		if (in_array($oldStatus,$stockOut) && !in_array($newStatus,$stockOut)) //was "unshipped"
    			$inStock+=$newQuantity;
    		elseif (!in_array($oldStatus,$stockOut) && in_array($newStatus,$stockOut)) //was "shipped"
    			$inStock-=$newQuantity;
    		
    		if (in_array($oldStatus,$reserved) && !in_array($newStatus,$reserved)) //was made "unreserved"
    			$ordered-=$newQuantity;
    		elseif (!in_array($oldStatus,$reserved) && in_array($newStatus,$reserved)) //was made "reserved"
    			$ordered+=$newQuantity;
    		
    		if ($inStock!=0 && $ordered!=0) //no "radical" change of state
    		{
    			$diff = $newQuantity-$oldQuantity; 
    			if ($diff!=0) //can be quantity changed: + added, - substracted
    			{
    				if (in_array($newStatus,$reserved)) //status is "reserved"
    					$ordered += $diff;
    				if (in_array($newStatus,$stockOut)) //status is "shipped"
    					$inStock -= $diff;
    			}
    		}

			if ($inStock!=0)
				$change[]=' product_in_stock = product_in_stock '.($inStock>0 ? '+ ' : '- ').abs($inStock);
				
			if ($ordered!=0)
				$change[]=' product_ordered = product_ordered '.($ordered>0 ? '+ ' : '- ').abs($ordered);
    	}

    	if (count($change)){   	
        	$this->_db->setQuery('UPDATE #__virtuemart_products SET '.
        	implode(', ',$change).
        	' WHERE virtuemart_product_id = '.(int)$product_id);
        	return $this->_db->query();
        }
        return null;
    }
    */
}

?>